<template>
	<!-- #ifndef APP-NVUE -->
	<view
		class="u-grid-item"
		hover-class="u-grid-item--hover-class"
		:hover-stay-time="200"
		@tap="clickHandler"
		:class="classes"
		:style="[itemStyle]"
	>
		<slot />
	</view>
	<!-- #endif -->
	<!-- #ifdef APP-NVUE -->
	<view
		class="u-grid-item"
		:hover-stay-time="200"
		@tap="clickHandler"
		:class="classes"
		:style="[itemStyle]"
	>
		<slot />
	</view>
	<!-- #endif -->
</template>

<script>
import props from './props.js'
import mpMixin from '../../libs/mixin/mpMixin.js'
import mixin from '../../libs/mixin/mixin.js'
/**
 * gridItem 提示
 * @description 宫格组件一般用于同时展示多个同类项目的场景，可以给宫格的项目设置徽标组件(badge)，或者图标等，也可以扩展为左右滑动的轮播形式。搭配u-grid使用
 * @tutorial https://www.uviewui.com/components/grid.html
 * @property {String | Number}	name		宫格的name ( 默认 null )
 * @property {String}			bgColor		宫格的背景颜色 （默认 'transparent' ）
 * @property {Object}			customStyle	自定义样式，对象形式
 * @event {Function} click 点击宫格触发
 * @example <u-grid-item></u-grid-item>
 */
export default {
	name: 'u-grid-item',
	// #ifndef MP
	emits: ['click'],
	// #endif
	mixins: [mpMixin, mixin, props],
	data() {
		return {
			parentData: {
				col: 3, // 父组件划分的宫格数
				border: true // 是否显示边框，根据父组件决定
			},
			// #ifdef APP-NVUE
			width: 0, // nvue下才这么计算，vue下放到computed中，否则会因为延时造成闪烁
			// #endif
			classes: [] // 类名集合，用于判断是否显示右边和下边框
		}
	},
	mounted() {
		this.init()
	},
	computed: {
		// #ifndef APP-NVUE
		// vue下放到computed中，否则会因为延时造成闪烁
		width() {
			return 100 / Number(this.parentData.col) + '%'
		},
		// #endif
		itemStyle() {
			const style = {
				background: this.bgColor,
				width: this.width
			}
			return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle))
		}
	},
	methods: {
		init() {
			// 用于在父组件u-grid的children中被添加入子组件时，
			// 重新计算item的边框
			uni.$on('$uGridItem', () => {
				this.gridItemClasses()
			})
			// 父组件的实例
			this.updateParentData()
			// #ifdef APP-NVUE
			// 获取元素该有的长度，nvue下要延时才准确
			this.$nextTick(function () {
				this.getItemWidth()
			})
			// #endif
			// 发出事件，通知所有的grid-item都重新计算自己的边框
			uni.$emit('$uGridItem')
			this.gridItemClasses()
		},
		// 获取父组件的参数
		updateParentData() {
			// 此方法写在mixin中
			this.getParentData('u-grid')
		},
		clickHandler() {
			let name = this.name
			// 如果没有设置name属性，历遍父组件的children数组，判断当前的元素是否和本实例this相等，找出当前组件的索引
			const children = this.parent?.children
			if (children && this.name === null) {
				name = children.findIndex(child => child === this)
			}
			// 调用父组件方法，发出事件
			this.parent && this.parent.childClick(name)
			this.$emit('click', name)
		},
		async getItemWidth() {
			// 如果是nvue，不能使用百分比，只能使用固定宽度
			let width = 0
			if (this.parent) {
				// 获取父组件宽度后，除以栅格数，得出每个item的宽度
				const parentWidth = await this.getParentWidth()
				width = parentWidth / Number(this.parentData.col) + 'px'
			}
			this.width = width
		},
		// 获取父元素的尺寸
		getParentWidth() {
			// #ifdef APP-NVUE
			// 返回一个promise，让调用者可以用await同步获取
			const dom = uni.requireNativePlugin('dom')
			return new Promise(resolve => {
				// 调用父组件的ref
				dom.getComponentRect(this.parent.$refs['u-grid'], res => {
					resolve(res.size.width)
				})
			})
			// #endif
		},
		gridItemClasses() {
			if (this.parentData.border) {
				let classes = []
				this.parent.children.map((child, index) => {
					if (this === child) {
						const len = this.parent.children.length
						// 贴近右边屏幕边沿的child，并且最后一个（比如只有横向2个的时候），无需右边框
						if ((index + 1) % this.parentData.col !== 0 && index + 1 !== len) {
							classes.push('u-border-right')
						}
						// 总的宫格数量对列数取余的值
						// 如果取余后，值为0，则意味着要将最后一排的宫格，都不需要下边框
						const lessNum =
							len % this.parentData.col === 0 ? this.parentData.col : len % this.parentData.col
						// 最下面的一排child，无需下边框
						if (index < len - lessNum) {
							classes.push('u-border-bottom')
						}
					}
				})
				// 支付宝，头条小程序无法动态绑定一个数组类名，否则解析出来的结果会带有","，而导致失效
				// #ifdef MP-ALIPAY || MP-TOUTIAO
				classes = classes.join(' ')
				// #endif
				this.classes = classes
			}
		}
	},
	beforeDestroy() {
		// 移除事件监听，释放性能
		uni.$off('$uGridItem')
	}
}
</script>

<style lang="scss" scoped>
@import '../../libs/css/components.scss';
$u-grid-item-hover-class-opcatiy: 0.5 !default;
$u-grid-item-margin-top: 1rpx !default;
$u-grid-item-border-right-width: 0.5px !default;
$u-grid-item-border-bottom-width: 0.5px !default;
$u-grid-item-border-right-color: $u-border-color !default;
$u-grid-item-border-bottom-color: $u-border-color !default;
.u-grid-item {
	align-items: center;
	justify-content: center;
	position: relative;
	flex-direction: column;
	/* #ifndef APP-NVUE */
	box-sizing: border-box;
	display: flex;
	/* #endif */

	/* #ifdef MP */
	position: relative;
	float: left;
	/* #endif */

	/* #ifdef MP-WEIXIN */
	margin-top: $u-grid-item-margin-top;
	/* #endif */

	&--hover-class {
		opacity: $u-grid-item-hover-class-opcatiy;
	}
}

/* #ifdef APP-NVUE */
// 由于nvue不支持组件内引入app.vue中再引入的样式，所以需要写在这里
.u-border-right {
	border-right-width: $u-grid-item-border-right-width;
	border-color: $u-grid-item-border-right-color;
}

.u-border-bottom {
	border-bottom-width: $u-grid-item-border-bottom-width;
	border-color: $u-grid-item-border-bottom-color;
}

/* #endif */
</style>
